﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FIXForge.NET.FIX;
using Algo;
using TAS;
using System.IO;
using System.Security.Cryptography;


namespace SimulationStation
{
    public partial class SimulationForm : Form
    {
        int OrderCount = 1, TradeCount = 1;

        public SimulationForm()
        {
            InitializeComponent();
        }

        private void StartBtn_Click(object sender, EventArgs e)
        {
            StartBtn.Enabled = false;
            bool encode = false;

            EngineSettings settings = new EngineSettings();

            // use Dialect.xml to Encode, FixDialectDescription.xml for Handler

            if (encode == true)
            {
                settings.Dialect = "Dialect.xml";
            }
            else
            {
                settings.Dialect = "FixDialectDescription.xml";
            }

            settings.LogDirectory = "\\Logs";
            Engine.Init(settings);

            AlgoEngine algoEngine = new AlgoEngine();

            algoEngine.simulation = false;

            algoEngine.OnLogMessageHandler += new AlgoEngine.LogMessageHandler(OnLogMessageHandler);
            algoEngine.OnOrderUpdate += new AlgoEngine.OrderUpdate(OnOrderUpdate);
            algoEngine.OnTradeDataUpdate += new AlgoEngine.TradeDataUpdate(OnTradeDataUpdate);
            algoEngine.tasEngine.OnHandlerStateChanged += new TAS.TASEngine.HandlerStateChanged(OnHandlerStateChanged);

            algoEngine.Initialize();
        }

        private delegate void UpdateTradeDataGridView(double tradeId, int type, string status, double netGain);

        void OnTradeDataUpdate(double tradeId, int type, string status, double netGain)
        {
            if (this.tradeDataGridView.InvokeRequired)
            {
                tradeDataGridView.BeginInvoke(new UpdateTradeDataGridView(OnTradeDataUpdate), new object[] { tradeId, type, status, netGain });
            }
            else
            {
                foreach (DataGridViewRow row in OrderDataGridView.Rows)
                {
                    if (tradeId.ToString() == row.Cells[1].Value.ToString() )
                    {
                        row.Cells[3].Value = status;
                        row.Cells[4].Value = netGain;
                        return;
                    }
                }

                tradeDataGridView.Rows.Add(TradeCount++, tradeId, type, status, netGain);
            }
        }

        private delegate void UpdateOrderDataGridView(string orderID, double tradeId, string securityID, string type, double price, string status);

        void OnOrderUpdate(string orderID, double tradeId, string securityID, string type, double price, string status)
        {
            if (this.OrderDataGridView.InvokeRequired)
            {
                OrderDataGridView.BeginInvoke(new UpdateOrderDataGridView(OnOrderUpdate), new object[] { orderID, tradeId, securityID, type, price, status });
            }
            else
            {
                foreach (DataGridViewRow row in OrderDataGridView.Rows)
                {
                    if (row.Cells[1].ToString() == orderID)
                    {
                        row.Cells[6].Value = status;
                        return;
                    }
                }

                OrderDataGridView.Rows.Add(OrderCount++, orderID, securityID, tradeId, type, price, status);
            }
        }

        private delegate void UpdateHandlerStatusMessage(string message);

        void OnHandlerStateChanged(string message)
        {
            if (this.StatusLbl.InvokeRequired)
            {
                StatusLbl.BeginInvoke(new UpdateLogMessage(OnHandlerStateChanged), new object[] { message });
            }
            else
            {
                StatusLbl.Text = message;
            }
        }

        private delegate void UpdateLogMessage(string message);

        void OnLogMessageHandler(string message)
        {
            if( this.LogsTxtBx.InvokeRequired )
            {
                LogsTxtBx.BeginInvoke(new UpdateLogMessage(OnLogMessageHandler), new object[] {message});
            }
            else
            {
                LogsTxtBx.Text += message + "\n";
            }
        }

        private DateTime DSTime(string str1)
        {
            DateTime dt = new DateTime(10, 10, 10, 0, 0, 0, 0);
            int y, m, d, h, mi, ss, ms;
            char[] str;
            string s;
            str = str1.ToCharArray();
            s = new string(str, 0, 4);
            y = (int)ConvertToLong(s);
            s = new string(str, 4, 2);
            m = (int)ConvertToLong(s);
            s = new string(str, 6, 2);
            d = (int)ConvertToLong(s);
            s = new string(str, 8, 2);
            h = (int)ConvertToLong(s);
            s = new string(str, 10, 2);
            mi = (int)ConvertToLong(s);
            s = new string(str, 12, 2);
            ss = (int)ConvertToLong(s);
            s = new string(str, 14, 3);
            ms = (int)ConvertToLong(s);
            dt = new DateTime(y, m, d, h, mi, ss, ms);
            return dt;
        }

        private long ConvertToLong(string str1)
        {
            char[] str = str1.ToCharArray();
            long i = str1.Length;
            long number = 0;
            for (int j = 0; j < i; j++)
            {
                if (str[j] == '0')
                    number = number * 10 + 0;
                else if (str[j] == '1')
                    number = number * 10 + 1;
                else if (str[j] == '2')
                    number = number * 10 + 2;
                else if (str[j] == '3')
                    number = number * 10 + 3;
                else if (str[j] == '4')
                    number = number * 10 + 4;
                else if (str[j] == '5')
                    number = number * 10 + 5;
                else if (str[j] == '6')
                    number = number * 10 + 6;
                else if (str[j] == '7')
                    number = number * 10 + 7;
                else if (str[j] == '8')
                    number = number * 10 + 8;
                else if (str[j] == '9')
                    number = number * 10 + 9;
            }

            return number;
        }

        private bool AESEncryption( string password )
        {
            try
            {

                string original = "Here is some data to encrypt!";

                // Create a new instance of the Aes 
                // class.  This generates a new key and initialization  
                // vector (IV). 
                using (Aes myAes = Aes.Create())
                {

                    myAes.Key = Encoding.ASCII.GetBytes("RememberRememberThe5thofNovember");
                    myAes.IV = Encoding.ASCII.GetBytes("SteveJobsiPhone5");

                    // Encrypt the string to an array of bytes. 
                    byte[] encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV);

                    // Decrypt the bytes to a string. 
                    string roundtrip = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV);

                    //Display the original data and the decrypted data.
                    //MessageBox.Show("Encrypted  " + Encoding.ASCII.GetString(encrypted));

                    //if ( Encoding.ASCII.GetBytes(roundtrip) == encrypted )
                    if ( password.Equals(Encoding.ASCII.GetString(encrypted)))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }

            }
            catch (Exception e)
            {
                return false;
            }
        }

        static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
        {
            // Check arguments. 
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");
            byte[] encrypted;
            // Create an Aes object 
            // with the specified key and IV. 
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for encryption. 
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }

            // Return the encrypted bytes from the memory stream. 
            return encrypted;
        }

        static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments. 
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");

            // Declare the string used to hold 
            // the decrypted text. 
            string plaintext = null;

            // Create an Aes object 
            // with the specified key and IV. 
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption. 
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            return plaintext;

        }
    }
}
